package utility;

import java.io.*;
import java.util.*;

import javax.xml.namespace.*;
import javax.xml.stream.*;

import com.siemens.ct.exi.*;
import com.siemens.ct.exi.api.stream.*;
import com.siemens.ct.exi.exceptions.*;
import com.siemens.ct.exi.helpers.*;
import com.thoughtworks.xstream.converters.*;
import com.thoughtworks.xstream.io.*;
import com.thoughtworks.xstream.io.xml.*;

public class ExiReader implements HierarchicalStreamReader {

   private StaxReader reader;
   
   public ExiReader (InputStream in) throws EXIException, IOException, XMLStreamException {
      reader = new StaxReader(new QNameMap(), new ExiStreamReader(in));
   }
   
   @Override
   public boolean hasMoreChildren() {
      
      return reader.hasMoreChildren();
   }

   @Override
   public void moveDown() {
      reader.moveDown();      
   }

   @Override
   public void moveUp() {
      reader.moveUp();      
   }

   @Override
   public String getNodeName() {
      return reader.getNodeName();
   }

   @Override
   public String getValue() {
      return reader.getValue();
   }

   @Override
   public String getAttribute(String name) {
      return reader.getAttribute(name);
   }

   @Override
   public String getAttribute(int index) {
      return reader.getAttribute(index);
   }

   @Override
   public int getAttributeCount() {
      return reader.getAttributeCount();
   }

   @Override
   public String getAttributeName(int index) {
      return reader.getAttributeName(index);
   }

   @SuppressWarnings("rawtypes")
   @Override
   public Iterator getAttributeNames() {
      return reader.getAttributeNames();
   }

   @Override
   public void appendErrors(ErrorWriter errorWriter) {
      reader.appendErrors(errorWriter);      
   }

   @Override
   public void close() {
      reader.close();      
   }

   @Override
   public HierarchicalStreamReader underlyingReader() {
      return reader.underlyingReader();
   }

   private static class ExiStreamReader implements XMLStreamReader {

      private StAXDecoder decoder;
      
      public ExiStreamReader (InputStream in) throws EXIException, IOException, XMLStreamException {
         // Build the EXI writer
         EXIFactory factory = DefaultEXIFactory.newInstance();
         factory.setCodingMode(CodingMode.COMPRESSION);
         
         decoder = new StAXDecoder(factory);
         decoder.setInputStream(in);
      }
      
      @Override
      public void close() throws XMLStreamException {
         decoder.close();
      }

      @Override
      public int getAttributeCount() {
         return decoder.getAttributeCount();
      }

      @Override
      public String getAttributeLocalName(int arg0) {
         
         return decoder.getAttributeLocalName(arg0);
      }

      @Override
      public QName getAttributeName(int arg0) {
         
         return decoder.getAttributeName(arg0);
      }

      @Override
      public String getAttributeNamespace(int arg0) {
         
         return decoder.getAttributeNamespace(arg0);
      }

      @Override
      public String getAttributePrefix(int arg0) {
         
         return decoder.getAttributePrefix(arg0);
      }

      @Override
      public String getAttributeType(int arg0) {
         
         return decoder.getAttributeType(arg0);
      }

      @Override
      public String getAttributeValue(int arg0) {
         
         return decoder.getAttributeValue(arg0);
      }

      @Override
      public String getAttributeValue(String arg0, String arg1) {
         
         return decoder.getAttributeValue(arg0, arg1);
      }

      @Override
      public String getCharacterEncodingScheme() {
         
         return decoder.getCharacterEncodingScheme();
      }

      @Override
      public String getElementText() throws XMLStreamException {
         
         return decoder.getElementText();
      }

      @Override
      public String getEncoding() {
         
         return decoder.getEncoding();
      }

      @Override
      public int getEventType() {
         
         return decoder.getEventType();
      }

      @Override
      public String getLocalName() {
         
         return decoder.getLocalName();
      }

      @Override
      public Location getLocation() {
         
         return decoder.getLocation();
      }

      @Override
      public QName getName() {
         
         return decoder.getName();
      }

      @Override
      public NamespaceContext getNamespaceContext() {
         
         return decoder.getNamespaceContext();
      }

      @Override
      public int getNamespaceCount() {
         
         return decoder.getNamespaceCount();
      }

      @Override
      public String getNamespacePrefix(int arg0) {
         
         return decoder.getNamespacePrefix(arg0);
      }

      @Override
      public String getNamespaceURI() {
         
         return decoder.getNamespaceURI();
      }

      @Override
      public String getNamespaceURI(String arg0) {
         
         return decoder.getNamespaceURI(arg0);
      }

      @Override
      public String getNamespaceURI(int arg0) {
         
         return decoder.getNamespaceURI(arg0);
      }

      @Override
      public String getPIData() {
         
         return decoder.getPIData();
      }

      @Override
      public String getPITarget() {
         
         return decoder.getPITarget();
      }

      @Override
      public String getPrefix() {
         
         return decoder.getPrefix();
      }

      @Override
      public Object getProperty(String arg0) throws IllegalArgumentException {
         
         return decoder.getProperty(arg0);
      }

      @Override
      public String getText() {
         
         return decoder.getText();
      }

      @Override
      public char[] getTextCharacters() {
         
         return decoder.getTextCharacters();
      }

      @Override
      public int getTextCharacters(int arg0, char[] arg1, int arg2, int arg3)
            throws XMLStreamException {
         
         return decoder.getTextCharacters(arg0, arg1, arg2, arg3);
      }

      @Override
      public int getTextLength() {
         
         return decoder.getTextLength();
      }

      @Override
      public int getTextStart() {
         
         return decoder.getTextStart();
      }

      @Override
      public String getVersion() {
         
         return decoder.getVersion();
      }

      @Override
      public boolean hasName() {
         
         return decoder.hasName();
      }

      @Override
      public boolean hasNext() throws XMLStreamException {
         
         return decoder.hasNext();
      }

      @Override
      public boolean hasText() {
         
         return decoder.hasText();
      }

      @Override
      public boolean isAttributeSpecified(int arg0) {
         
         return decoder.isAttributeSpecified(arg0);
      }

      @Override
      public boolean isCharacters() {
         
         return decoder.isCharacters();
      }

      @Override
      public boolean isEndElement() {
         
         return decoder.isEndElement();
      }

      @Override
      public boolean isStandalone() {
         
         return decoder.isStandalone();
      }

      @Override
      public boolean isStartElement() {
         
         return decoder.isStartElement();
      }

      @Override
      public boolean isWhiteSpace() {
         
         return decoder.isWhiteSpace();
      }

      @Override
      public int next() throws XMLStreamException {
         
         return decoder.next();
      }

      @Override
      public int nextTag() throws XMLStreamException {
         return decoder.nextTag();
      }

      @Override
      public void require(int arg0, String arg1, String arg2)
            throws XMLStreamException {
         decoder.require(arg0, arg1, arg2);
      }

      @Override
      public boolean standaloneSet() {
         return decoder.standaloneSet();
      }
      
   }
}
